package utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

public class CodeUtil implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	public String createCode(int disturbType, int fontSize, ByteArrayOutputStream bos, int width, int height, int codeLength) {
		BufferedImage bImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = bImg.getGraphics();
		Random random = new Random();
		if (fontSize >= height) {
			fontSize = height - 1;
		}
		drawOutline(g, width, height);
		switch (disturbType) {
		case 1:
			drawSimpleDisturb(g, random, width, height);
			break;
		case 2:
			drawDisturb(g, random, width, height);
			break;
		default:
			break;
		}
		String code = drawCode(g, random, codeLength, width, height, fontSize);
		g.dispose();
		try {
			ImageOutputStream imOut = ImageIO.createImageOutputStream(bos);
			ImageIO.write(bImg, "JPEG", imOut);
			imOut.close();
			imOut.reset();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return code;
	}

	private static void drawOutline(Graphics g, int width, int height) {
		g.setColor(Color.white);
		g.fillRect(0, 0, width, height);
		g.setColor(Color.BLACK);
		g.drawRect(0, 0, width - 1, height - 1);
	}

	private static void drawDisturb(Graphics g, Random random, int width, int height) {
		int x, y, x1, y1;
		for (int i = 0; i < width; i++) {
			x = random.nextInt(width);
			y = random.nextInt(height);
			x1 = random.nextInt(12);
			y1 = random.nextInt(12);
			g.setColor(getRandomColor(random, 120, 255));
			g.drawLine(x, y, x + x1, y + y1);
			g.fillArc(x, y, x1, y1, random.nextInt(360), random.nextInt(360));
		}
	}

	private static void drawSimpleDisturb(Graphics g, Random random, int width, int height) {
		g.setColor(getRandomColor(random, 160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
	}

	private static Color getRandomColor(Random random, int pMin, int pMax) {
		pMax = (Math.abs(pMax) > 255 ? 255 : Math.abs(pMax));
		pMin = (Math.abs(pMin) > 255 ? 255 : Math.abs(pMin));
		int r = pMin + random.nextInt(Math.abs(pMax - pMin));
		int g = pMin + random.nextInt(Math.abs(pMax - pMin));
		int b = pMin + random.nextInt(Math.abs(pMax - pMin));
		return new Color(r, g, b);
	}

	private static String drawCode(Graphics g, Random random, int codeLength, int width, int height, int fontSize) {
		Font font1 = new Font("Verdana", Font.BOLD, fontSize);
		Font font2 = new Font("serif", Font.BOLD, fontSize);
		StringBuffer sb = new StringBuffer();
		int x, y;
		for (int i = 0; i < codeLength; i++) {
			x = (width / codeLength - 1) * i + random.nextInt(width / (codeLength * 2));
			y = random.nextInt(height - fontSize) + fontSize;
			sb.append(random.nextInt(10));
			g.setColor(getRandomColor(random, 70, 150));
			if (sb.substring(i).getBytes().length > 1)
				g.setFont(font2);
			else
				g.setFont(font1);
			g.drawString(sb.substring(i), x, y);
		}
		return sb.toString();
	}
}
